-
Notifications
You must be signed in to change notification settings - Fork 14k
add must_use to extract_if methods #148995
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be nicer if we had map.range_mut(..).discard() and similar range operations. But until then extract_if is the best we offer... ok.
| /// assert_eq!(high.keys().copied().collect::<Vec<_>>(), [4, 5, 6, 7]); | ||
| /// ``` | ||
| #[stable(feature = "btree_extract_if", since = "1.91.0")] | ||
| #[must_use = "use `extract_if().for_each(drop)` to remove all extracted elements"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wording we have on most iterators is simply
#[must_use = "iterators are lazy and do nothing unless consumed"]
It's possible that the user meant to use the iterator results but forgot to somehow.
for_each(drop) is only recommended by an unused collect()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The drain iterator is also lazy and still does something when not consumed... so if the user knows drain, which is likely, then just talking about the laziness of iterators in general is not enough for this specific case IMO. I think it makes sense to tell people how to use this as a drain-like API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drain is an exception and we deliberately renamed it from DrainFilter to ExtractIf to avoid that association.
I guess you could add the general "iterators are lazy" statement and follow up with a "use retain or for_each(drop)" after that.
Generally we don't want to encourage for_each(drop) too much because it can indicate misuse such as iter.inspect(side_effect).for_each(drop) instead of iter.for_each(side_effect). But in this case it's a legitimate use, due to lack of better alternatives.
When we have a better alternative we can remove the for_each part of the hint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated the wording:
#[must_use = "this iterator is lazy and does nothing unless consumed; \
use `retain` or `extract_if().for_each(drop)` to remove and discard elements"]
I went for "this iterator" to make it more clear that this applies to extract_if despite potentially conflicting expectations raised by drain. (I also considered something like "the iterator returned by extract_if" but found that too wordy.)
59d5167 to
0604669
Compare
| /// ``` | ||
| #[stable(feature = "btree_extract_if", since = "1.91.0")] | ||
| #[must_use = "this iterator is lazy and does nothing unless consumed; \ | ||
| use `retain` or `extract_if().for_each(drop)` to remove and discard elements"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we remind people that retain needs the predicate to be negated?
Alternatively we could only mention the for_each variant here. We do still mention retain in the docs for people that have a closer look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
must_use hints seem to be terse in general. I assume this is to not bloat diagnostics, so let's keep it this way.
| #[must_use = "this iterator is lazy and does nothing unless consumed; \ | ||
| use `extract_if().for_each(drop)` to remove and discard elements"] | ||
| pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, K, V, F> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The functions without range arguments should only point to retain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right, I forgot the Hash* collections have those
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW personally I would probably still use extract_if in situations where the negation enforced by retain is awkward... in most of these cases, I want to characterize the elements to be removed, and then extract_if(...).for_each(drop) might beat retain(with-negation).
|
The |
Good point! I did that. |
|
@bors r+ rollup |
Rollup of 7 pull requests Successful merges: - #148703 (Use `overflow_checks` intrinsic so `IterRangeFrom` yields MAX before panicking in debug) - #148881 (use `cfg_select!` to pick assembly in codegen test) - #148911 (Make flags from `*FLAGS*` (such as `RUSTFLAGS`) env. vars. have precedence over flags set by bootstrap) - #148914 (fix incorrect import in `std_detect` on `aarch64-unknown-openbsd`) - #148971 (Document Error::{new,other} as to be avoided in pre_exec) - #148983 (Use rustc target metadata for build-manifest target lists) - #148995 (add must_use to extract_if methods) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of #148995 - RalfJung:extract_if, r=the8472 add must_use to extract_if methods Also, mention the `.for_each(drop)` pattern in the documentation. One can't always use `retain` with a negated predicate as that does not have a range argument. r? `@the8472`
|
still in queue @bors r- |
…iaskrgr Rollup of 7 pull requests Successful merges: - rust-lang#148703 (Use `overflow_checks` intrinsic so `IterRangeFrom` yields MAX before panicking in debug) - rust-lang#148881 (use `cfg_select!` to pick assembly in codegen test) - rust-lang#148911 (Make flags from `*FLAGS*` (such as `RUSTFLAGS`) env. vars. have precedence over flags set by bootstrap) - rust-lang#148914 (fix incorrect import in `std_detect` on `aarch64-unknown-openbsd`) - rust-lang#148971 (Document Error::{new,other} as to be avoided in pre_exec) - rust-lang#148983 (Use rustc target metadata for build-manifest target lists) - rust-lang#148995 (add must_use to extract_if methods) r? `@ghost` `@rustbot` modify labels: rollup
Also, mention the
.for_each(drop)pattern in the documentation. One can't always useretainwith a negated predicate as that does not have a range argument.r? @the8472